import os

import sys
from typing import Dict, Any

from apscheduler.events import EVENT_JOB_EXECUTED, EVENT_JOB_ERROR
from flask_apscheduler import APScheduler
from flask import Flask, jsonify, request, abort, make_response,render_template

import jwt

import logging

from logging.config import fileConfig

import datetime

import json

import schedule
from pymongo.cursor import Cursor

from schedule import every, repeat, run_pending

import time

from functools import wraps

import configparser

from datetime import datetime

import hashlib

from mongo.MongoHelper import MongoHelper


from findata.akshare.AkshareWeekly import AkshareWeekly
from findata.akshare.AkshareDaily import AkshareDaily
from findata.akshare.AkshareQuarterly import AkshareQuarterly
from findata.akshare.AkshareMonthly import AkshareMonthly
from findata.akshare.AkshareBiWeekly import AkshareBiWeekly
from findata.akshare.AkshareYearly import AkshareYearly


fileConfig('logging_config.ini', disable_existing_loggers=False)

app = Flask(__name__)
scheduler = APScheduler()
scheduler.init_app(app)
scheduler.start()

logger = logging.getLogger('simple_example')

# 这是一个示例密钥，实际应用中应该使用一个复杂且随机的密钥
app.config['SECRET_KEY'] = '=&RkmFvgRwyA'

mongoHelper = None
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
app.logger.info(os.path.join(BASE_DIR,'/conf.ini'))
cfgdir = os.path.split(os.path.realpath(__file__))[0]
app.logger.info(cfgdir)
cfg = os.path.join(cfgdir, 'conf.ini')
app.logger.info(cfg)

#
config = configparser.ConfigParser()
print(sys.argv)
if len(sys.argv) >= 2:
    config.read(sys.argv[1])
else:
    config.read('conf.ini',encoding='utf8')

database = config.get('db', 'database')
myUrl = config.get('db', 'url')
mongoHelper = MongoHelper(url=myUrl, database=database)
akshareWeekly = AkshareWeekly(cfg=cfg)
def token_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        token = None
        if 'Authorization' in request.headers:
            auth_header = request.headers['Authorization']
            if auth_header.startswith('Bearer '):
                token = auth_header.split(" ")[1]  # 分割"Bearer "和token

        if not token:
            return jsonify({'message': 'Token is missing!'}), 403
        try:
            data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=["HS256"])
            print(data)
            exp = int(data.pop("exp"))
            if time.time() > exp:
                return jsonify({'message': ''})
            elif time.time()> (exp- 3600 * 12 * 3):
                return jsonify({'message':''})
            else:
                return jsonify({'message':''})

        except:
            return jsonify({'message': 'Token is invalid!'}), 403
        finally:
            print()
        return f(*args, **kwargs)
    return decorated


@app.before_request
def before_request():
    # 在这里可以访问request的属性和方法
    print(request.method)
    print(request.path)

    # logger.info(f"收到请求{ json.dumps(request.data)}")
    # 可以修改request的数据
    # 例如: request.data = "new data"

@app.after_request
def after_request(response):
    # 在这里可以访问和修改响应对象response
    response.headers['Custom-Header'] = 'Custom Value'
    # 返回响应对象response
    logger.info(f"返回{response}")
    return response

@app.errorhandler(404)
def error(error):
    return render_template('404.html')
@app.route('/unprotected')
def unprotected():
    return jsonify({'message': 'Anyone can view this!'})


# curl -X  GET -H "Authorization:Bearer 111111" -H "Content-Type: application/json"  http://localhost:6000/protected
@app.route('/protected')
@token_required
def protected():
    return jsonify({'message': 'This is only available for people with valid tokens.'})

@app.route('/login',methods=['POST'])
def login():
    '''
    -u是对应authorization -d 对应的是application/json
    curl -vvv -u admin:password -X POST -H "Content-Type: application/json" -d '{"username":"user", "password":"pass"}' http://localhost:6000/login
    '''
    auth = request.authorization
    print(request.json.get("username"))
    password = request.json.get("password")
    username = request.json.get("username")
    encrypted = None
    if username is None or password is None or (auth and auth.password is None) or (auth and auth.username is None):
        return make_response()
    else:
        m = hashlib.md5()
        m.update(password.encode("utf-8"))
        print(m.hexdigest())
        encrypted = m.hexdigest()

    if encrypted is not None:
        coll = mongoHelper.mongo_db.get_collection('sysUsers')
        qCon: dict[str, Any] = {'username': request.json.get("username"), 'password': encrypted,'status': 'Y'}
        res = coll.find_one(qCon)
        if res is not None:
            print(int(time.time()) + 3600 * 24 * 3)

            token = jwt.encode({
                'user': username,
                'id': str(res['_id']),
                'exp': int(time.time()) + 3600 * 24 * 3
            }, app.config['SECRET_KEY'], algorithm="HS256")

            return jsonify({'token': token, 'username': username, 'password': password, 'role': 'admin', 'roleId':1, 'permissions': ['*.*.*']})
        else:
            print()
    return make_response('Could not verify!', 401, {'WWW-Authenticate': 'Basic realm="Login Required"'})

# curl -X  POST -H "Content-Type: application/json" -d '{"username":"test1", "password":"test1"}' http://localhost:6000/register
@app.route('/register',  methods=['POST'])
def register():
    print('')
    password = request.json.get("password")
    username = request.json.get("username")
    encrypted = None
    if username is not None and password is not None and len(username)>0 and len(password)>0:
        coll = mongoHelper.mongo_db.get_collection('sysUsers')
        qCon: dict[str, Any] = {'username': username}
        result = coll.find_one(qCon)
        if result is None:
            m = hashlib.md5()
            m.update(password.encode("utf-8"))
            print(m.hexdigest())
            encrypted = m.hexdigest()
            record = {'username': request.json.get("username"), 'password': encrypted, 'status': 'Y', 'createdTime': datetime.now(),'source': '', 'cate': '1', 'cellphone': ''}
            cnt = coll.insert_one(record)
            print(f'{cnt.inserted_id}')
            return jsonify({'code':'0000','msg':'Success'})
        else:
            print(f'{username}已经存在至少一个')
            return jsonify({'code':'0001','msg':'existing'})
    else:
        return make_response('username not found', 404, {'WWW-Authenticate': 'Basic realm=""'})

def theJob():
    print('The job is running')
    app.logger.info("================================")

def my_job(name, age):
    print(f"Hello, {name}! You are {age} years old.")

# 此装饰器效果等同于 schedule.every(10).minutes.do(job)
@repeat(every(2).minutes)
def job():
    print(" I am now")
    app.logger.info("I am a scheduled job")

def blah(event):
    with scheduler.app.app_context():
        if event.exception:
            print('The job crashed :(')
        else:
            print('The job worked :)')

scheduler.add_listener(blah, EVENT_JOB_EXECUTED | EVENT_JOB_ERROR)



@scheduler.task('interval', id='do_job_1', seconds=30, misfire_grace_time=900)
def job1():
    app.logger.info('Job 1 executed')

@scheduler.task('cron', id='do_job_2', hour=1, minute=5)
def equity_his():
    list = akshareWeekly.get_all_equities()
    for rec in list:
        akshareWeekly.ahist(symbol=rec['code'], period='daily', start_date='20240101', end_date='20240620', adjust='hfq')

if __name__ == '__main__':



    # akshareWeekly.ahist(symbol='600487', period='', start_date='', end_date='', adjust='')
    # akshareWeekly.industryFlow()
    # akshareWeekly.blockTransactionDetails(symbol='A股',  startDate='20240101', endDate='20240131')
    # akshareWeekly.holder(symbol='全部')
    # akshareWeekly.bigdealtrack()
    # akshareWeekly.numofretailinvestor(symbol='20231231')
    # akshareWeekly.fundHolder(symbol='基金持仓',begdate='20240501')
    # akshareWeekly.assetbalance(begdate='20231231')
    # akshareWeekly.cashflow(begdate='20231231')
    # akshareWeekly.financialindicator(symbol='600487',begdate='2023')

    # akshareWeekly.hkfinancialindicator(symbol='600487',begdate='2023')

    # akshareWeekly.freeHolder(symbol='sh600487',begdate='20231231')

    # akshareWeekly.conceptcashflow(symbol='即时')

    scheduler.add_job(id='theJob', func=theJob, trigger='interval', minutes=1)

    # 使用lambda函数来包装你的任务和它的参数
    # schedule.every(10).seconds.do(lambda: job("Alice", 30))
    # schedule.every(10).seconds.do(my_job,name='Alice',age=30)
    # schedule.every().monday.do(theJob)
    # schedule.every(10).seconds.do(theJob)
    # 每十分钟执行任务
    # schedule.every(2).minutes.do(theJob)
    # 每个小时执行任务
    # schedule.every().hour.do(theJob)
    # 每天的10:30执行任务
    # schedule.every().day.at("00:50:00").do(lambda: akshareWeekly.basicInfo(symbol='600487'))
    # 每个月执行任务
    # schedule.every().monday.do(theJob)
    # 每个星期三的13:15分执行任务
    # schedule.every().wednesday.at("13:15").do(theJob)
    # 每分钟的第17秒执行任务
    # schedule.every().minute.at(":17").do(theJob)
    # do() 将额外的参数传递给job函数
    # schedule.every(2).seconds.do(greet, name='Alice')
    # all_jobs = schedule.get_jobs()

    # .tag 打标签
    # schedule.every().day.do(greet, 'Andrea').tag('daily-tasks', 'friend')

    # 每个小时运行作业，2030-01-01 18:33 today
    # schedule.every(1).hours.until("2030-01-01 18:33").do(job)

    # 每个小时运行作业，8个小时后停止
    # schedule.every(1).hours.until(timedelta(hours=8)).do(job)


    # schedule.clear()
    app.run(host='0.0.0.0', port=6000,debug=True)
    while True:
        schedule.run_pending()
        time.sleep(1)
